﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ALDIOrganizer.Properties;

namespace ALDIOrganizer
{
    public partial class RequestDetails : Form, IValidating
    {
        CheckBox[] cbWeekdays;
        Label[] lbWeekdays;

        internal Request DataBoundRequest
        {
            get
            {
                return requestBindingSource.DataSource as Request;
            }
            set
            {
                requestBindingSource.DataSource = value;
            }
        }

        public RequestDetails()
        {
            InitializeComponent();

            #region autogenerate mon-sun checkboxes & labels
            cbWeekdays = new CheckBox[7];
            lbWeekdays = new Label[7];

            for (int day = 0; day < 7; day++)
            {
                cbWeekdays[day] = new CheckBox
                                      {
                                          Anchor = AnchorStyles.Top,
                                          AutoSize = true,
                                          Margin = new Padding(0),
                                          TabIndex = day,
                                          Tag = day
                                      };

                lbWeekdays[day] = new Label
                                      {
                                          Anchor = AnchorStyles.Top,
                                          AutoSize = true,
                                          Margin = new Padding(0),
                                          Text = Time.ShortDayName(day)
                                      };

                tblWeekdays.Controls.Add(lbWeekdays[day], day, 0);
                tblWeekdays.Controls.Add(cbWeekdays[day], day, 1);
            }

            #endregion
        }

        public RequestDetails(DataRow pRow, InputAction pAction, bool? pPending)
            : this()
        {
            if (pAction == InputAction.Create)
            {
                DataBoundRequest = new Request(SQLiteAccess.SpawnRequestRow());
                btnClear_Click(null, null);
                // requestBindingSource.ResetBindings(false);            
            }
            if (pAction == InputAction.Update)
            {
                DataBoundRequest = new Request(pRow);
                requestBindingSource.ResetBindings(false);

                ReadIn();
            }


            if (!pPending.HasValue)
            {
                return;
            }
            rbConfirmed.Enabled = !pPending.Value;
            rbPending.Enabled = pPending.Value;
            rbConfirmed.Checked = !pPending.Value;
            rbPending.Checked = pPending.Value;
        }


        private void formRequest_Load(object sender, EventArgs e)
        {
            #region event handlers
            var radiobuttons = new RadioButton[] { rbHoursNo, rbHoursYes, rbUntilNotSpecified, rbUntilSameDay, rbUntilSpecified, rbWeekdaysNo, rbWeekdaysYes };
            foreach (RadioButton rb in radiobuttons)
                rb.CheckedChanged += (_sender, _e) => UpdateControls();
            foreach (DateTimePicker dt in new DateTimePicker[] { dtSince, dtUntil })
                dt.ValueChanged += (_sender, _e) => UpdateControls();

            #endregion




            mbAfter.DataBindings[0].Parse += new ConvertEventHandler(MaskedBox_Parse);
            mbBefore.DataBindings[0].Parse += new ConvertEventHandler(MaskedBox_Parse);
            mbAfter.Validating += new CancelEventHandler(MaskedBox_Validating);
            mbBefore.Validating += new CancelEventHandler(MaskedBox_Validating);
            // mbFrom.DataBindings[0].Format += new ConvertEventHandler(MaskedBox_Format);
            // btnClear_Click(null, null);

        }

        void MaskedBox_Validating(object sender, CancelEventArgs e)
        {
            var _control = sender as MaskedTextBox;
            if (_control == null)
            {
                return;
            }
            CheckBox _checkbox = null;
            var value = new TimeByQuarters?();
            if (_control == mbAfter)
            {
                _checkbox = cbHoursAfter;
                value = DataBoundRequest.ForbiddenAfterHour;
            }
            if (_control == mbBefore)
            {
                _checkbox = cbHoursBefore;
                value = DataBoundRequest.ForbiddenBeforeHour;
            }
            if (_checkbox != null &&
                value != (TimeByQuarters?)null)
            {
                _control.DataBindings[0].ReadValue();
                _checkbox.Checked = true;
            }
            else
            {
                _checkbox.Checked = false;
            }
        }

        void ReadIn()
        {
            if (!DataBoundRequest.endDate.HasValue)
                rbUntilNotSpecified.Checked = true;
            else
                if (DataBoundRequest.endDate == DataBoundRequest.startDate)
                    rbUntilSameDay.Checked = true;
                else
                    rbUntilSpecified.Checked = true;

            var forbidenBeforeHourSpecified = DataBoundRequest.ForbiddenBeforeHour.HasValue;
            var forbidenAfterHourSpecified = DataBoundRequest.ForbiddenAfterHour.HasValue;
            var noHoursSpecified = (!forbidenBeforeHourSpecified
                & !forbidenAfterHourSpecified);
            rbHoursNo.Checked = noHoursSpecified;
            rbHoursYes.Checked = !noHoursSpecified;
            cbHoursAfter.Checked = forbidenAfterHourSpecified;
            cbHoursBefore.Checked = forbidenBeforeHourSpecified;

            SetDayCheckboxes(DataBoundRequest.Days);
            if (DataBoundRequest.Days.Length > 0)
                rbWeekdaysYes.Checked = true;
            if (DataBoundRequest.Pending)
                rbPending.Checked = true;
            else
                rbConfirmed.Checked = true;
            UpdateControls();
        }

        Weekday[] GetDaysFromCheckboxes
        {
            get
            {
                return (from _checkbox in cbWeekdays
                        where _checkbox.Checked
                        select (Weekday)(int)_checkbox.Tag).ToArray();
            }
        }

        void SetDayCheckboxes(Weekday[] pDays)
        {
            foreach (var _day in pDays)
                cbWeekdays[_day.ToInt0()].Checked = true;
            foreach (var _day in pDays.Remaining())
                cbWeekdays[_day.ToInt0()].Checked = false;
        }

        internal Request FinalResult()
        {
            if (rbUntilSameDay.Checked)
            {
                DataBoundRequest.endDate = DataBoundRequest.startDate;
            }
            if (rbUntilNotSpecified.Checked)
            {
                DataBoundRequest.endDate = (DateTime?)null;
            }
            DataBoundRequest.Days = rbWeekdaysYes.Checked ?
                        GetDaysFromCheckboxes :
                        new Weekday[] { };
            if (rbHoursNo.Checked |
                !cbHoursBefore.Checked)
            {
                DataBoundRequest.ForbiddenBeforeHour = (TimeByQuarters?)null;
            }
            if (rbHoursNo.Checked |
                !cbHoursAfter.Checked)
            {
                DataBoundRequest.ForbiddenAfterHour = (TimeByQuarters?)null;
            }
            DataBoundRequest.Pending = rbPending.Checked;
            return DataBoundRequest;
        }

        static void MaskedBox_Parse(object sender, ConvertEventArgs e)
        {
            var _parse = TimeByQuarters.Parse(e.Value.ToString());
            if (_parse.Key)
            {
                e.Value = _parse.Value.AsNullable();
            }
            else
            {
                e.Value = (TimeByQuarters?)null;
            }
        }

        #region updating / clearing controls
        private void UpdateControls()
        {
            dtUntil.Enabled = rbUntilSpecified.Checked;
            rbUntilSameDay.Text = Resources.FORM_REQUESTDETAILS_rbxUntilSameDay.Replace(
                "#",
                dtSince.Value.Date.ToShortDateString());
            foreach (Control c in tblHours.Controls)
                c.Enabled = rbHoursYes.Checked;
            foreach (Control c in tblWeekdays.Controls)
                c.Enabled = rbWeekdaysYes.Checked;


        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            // dtSince.Value = DateTime.Now;
            (requestBindingSource.DataSource as Request).startDate = DateTime.Now;
            (requestBindingSource.DataSource as Request).Days = new Weekday[] { };
            rbUntilNotSpecified.Checked = true;
            rbWeekdaysNo.Checked = true;
            rbHoursNo.Checked = true;

            //    foreach (CheckBox cb in cbWeekdays)
            //      cb.Checked = false;
            cbHoursBefore.Checked = false;
            cbHoursAfter.Checked = false;

            mbAfter.Text = String.Empty;
            mbBefore.Text = String.Empty;
            tbReason.Text = String.Empty;
            
            if(rbConfirmed.Enabled)
            {
                rbConfirmed.Checked = true;
            }
            requestBindingSource.ResetBindings(false);
            UpdateControls();
        }
        #endregion

        #region validating data
        /// <summary>
        /// validates the input data
        /// </summary>
        /// <returns>key: 1 if OK, 0 if warning, -1 if invalid. Value: error pMessage</returns>
        public KeyValuePair<FormValidationResult, string> DoesValidate()
        {
            var validated = FormValidationResult.Fine;
            var message = String.Empty;

            if (rbUntilSpecified.Checked)
            {
                if (dtUntil.Value.Date < dtSince.Value.Date)
                {
                    validated = FormValidationResult.Error;
                    message = "Your time restriction cannot finish before it starts!";
                }
            }
            if(!(rbConfirmed.Checked | rbPending.Checked))
            {
                validated = FormValidationResult.Error;
                message = "You have not chosen whether the time-off request is pending or confirmed!";
            }
            return new KeyValuePair<FormValidationResult, string>(
                validated,
                message);
        }

        #endregion

        private void btnOK_Click(object sender, EventArgs e)
        {
            var foo = FinalResult();
            // System.Diagnostics.Debugger.Break();
        }
    }
}
